package com.cltech.frame.transformer;

import org.hibernate.transform.AliasedTupleSubsetResultTransformer;
import org.springframework.cglib.beans.BeanMap;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.util.StringUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * 查询结果集转Map（Key为数据库字段并且驼峰）.
 *
 * @author guanbo
 * @version 1.0.0.0
 */
public final class AliasToEntityCamelMapResultTransformer extends AliasedTupleSubsetResultTransformer {
    /**
     * AliasToEntityCamelMapResultTransformer实例.
     */
    public static final AliasToEntityCamelMapResultTransformer INSTANCE = new AliasToEntityCamelMapResultTransformer();

    /**
     * 构造方法.
     */
    private AliasToEntityCamelMapResultTransformer() {
    }

    /**
     * 下划线转驼峰.
     *
     * @param param 下划线
     * @return 驼峰
     */
    private static String underlineToCamel(String param) {
        if (param == null || "".equals(param.trim())) {
            return "";
        }
        param = param.toLowerCase();
        final int len = param.length();
        final StringBuilder sb = new StringBuilder(len);
        for (int i = 0; i < len; i++) {
            final char c = param.charAt(i);
            if (c == '_') {
                if (++i < len) {
                    sb.append(Character.toUpperCase(param.charAt(i)));
                }
            } else {
                sb.append(c);
            }
        }
        return sb.toString();
    }

    /**
     * 将结果集转换放到map中.
     *
     * @param tuple   值
     * @param aliases 字段名
     * @return map结果
     */
    public Object transformTuple(final Object[] tuple, final String[] aliases) {
         Map result = null;
        if (!aliasesIsEmpty(aliases)) {
            result = new HashMap(tuple.length);
            for (int i = 0; i < tuple.length; ++i) {
                final String alias = underlineToCamel(aliases[i]);
                if (alias != null) {
                    result.put(alias, tuple[i]);
                }
            }
        } else {
            if(tuple.length>1){
                throw new DataRetrievalFailureException("Use JpaQL select com.bidding.entity's property must add aliase");
            }else{
                final Object value = tuple[0];
                Class clazz = value.getClass();
                if (!isBaseClass(clazz)) {
                    result = BeanMap.create(value);
                } else {
                    throw new DataRetrievalFailureException("Use JpaQL select com.bidding.entity's property must add aliase");
                }
            }
        }
        return result;
    }
    private boolean isBaseClass(final Class clazz) {
        if (clazz.isPrimitive() || Number.class.isAssignableFrom(clazz) || clazz.isPrimitive()
                || String.class.isAssignableFrom(clazz) || Date.class.isAssignableFrom(clazz)) {
            return true;
        }
        return false;
    }
    private boolean aliasesIsEmpty(final String[] aliases) {
        for (int i = 0; i < aliases.length; i++) {
            final String column = aliases[i];
            if (StringUtils.isEmpty(column)) {
                return true;
            }
        }
        return false;
    }

    /**
     * isTransformedValueATupleElement.
     *
     * @param aliases     字段
     * @param tupleLength 长度
     * @return isTransformedValueATupleElement
     */
    public boolean isTransformedValueATupleElement(final String[] aliases, final int tupleLength) {
        return false;
    }

    /**
     * readResolve.
     *
     * @return 实例
     */
    private Object readResolve() {
        return INSTANCE;
    }
}
